package path;

import geom.Vector;

import java.util.ArrayList;
import java.util.Iterator;

import processing.core.PApplet;
import shapes.*;
import util.Color;
import util.RndGen;

public class DrawRandomShapes implements PathDrawer{
	RndGen random;
	Path path;
	ArrayList clusters;
	int clusterSize;
	float width;
	float shapeSize;
	
	public DrawRandomShapes(Path p, float width, int clusterSize, float shapeSize) {
		random = new RndGen();
		random.setSeed(RndGen.GOOD_SEED);
		clusters = new ArrayList();
		this.path = p;
		this.width = width;
		this.clusterSize = clusterSize;
		this.shapeSize = shapeSize;
		
	}
	
	private class ShapeCluster{
		Path path;
		int pathIndex;
		KeyFrame keyFrame;
		float before;
		float after;
		float width;
		float avgSize;
		int amount;
		ArrayList shapes;
		ArrayList positions;
		DrawRandomShapes parent;
		RndGen random;
		
		public ShapeCluster(DrawRandomShapes parent, int pathIndex, int amount, float width, float avgSize){
			this.parent = parent;
			random = parent.random;
			path = parent.path;
			this.width = width;
			this.avgSize = avgSize;
			this.pathIndex = pathIndex;
			this.amount = amount;
			keyFrame = path.getKeyFrameByIndex(pathIndex);
			
			if(pathIndex < path.keyFrames.size() - 1){
				Vector next = path.getKeyFrameByIndex(pathIndex + 1).getPosition();
				after = keyFrame.getPosition().getDistance(next) / 2f;
			}
			else after = 0;
			if(pathIndex > 0){
				Vector prev = path.getKeyFrameByIndex(pathIndex - 1).getPosition();
				after = keyFrame.getPosition().getDistance(prev) / 2f;
			}
			
			populate(amount, before, after, width, avgSize);
		}
		
		public void populate(int amount, float start, float end, float width, float avgSize){
			shapes = new ArrayList();
			positions = new ArrayList();
			if(start == 0 || end == 0)
				amount /= 2;
			
			for(int i = 0; i < amount; i++){
				Vector v = new Vector();
				v.x = random.rndUniform(-start, end);
				v.y = random.rndBetaDistributed(-width, width, 0.5f, 4);
				v.z = random.rndBetaDistributed(-width, width, 0.5f, 4);
				float size = random.rndBetaDistributed(avgSize - 0.25f * avgSize, avgSize - 0.25f * avgSize, 0.5f, 10);
				positions.add(v);
				shapes.add(new Cross(size, 1, new Color(160, 30, 235)));
			}
		}
		
		public void clusterAdded(){
			if(pathIndex < path.keyFrames.size() - 1){
				Vector next = path.getKeyFrameByIndex(pathIndex + 1).getPosition();
				after = keyFrame.getPosition().getDistance(next) / 2f;
			}
			populate(amount, 0, after, width, avgSize);
		}
		
		public void clusterRemoved(){
			before = 0;
		}
		
		public void draw(PApplet pa, Path path){
			if(keyFrame.getVisibility() == 0) return;
			
			Iterator ip = positions.iterator();
			Iterator is = shapes.iterator();
			int i = 0;
			int amount = Math.round(keyFrame.getVisibility() * shapes.size());
			
			while(ip.hasNext() && is.hasNext() && i < amount){
				Vector v = (Vector) ip.next();
				pa.pushMatrix();
				path.orientToPath(pa, pathIndex);
				//if(path.keyFrames.size() >= 50)
				//	System.out.println("break");
				if(!(before == 0 && v.x < 0) || !(after == 0 && v.x > 0)){
					pa.pushMatrix();
					pa.translate(v.x, v.y, v.z);
					Shape s = (Shape)is.next();
					s.scale(keyFrame.getVisibility());
					s.draw(pa);
					pa.popMatrix();
				}
				pa.popMatrix();
				i++;
			}
		}
	}
	
	public void drawPath(Path path, PApplet pa){
		for(int i = 0; i < clusters.size(); i++){
				((ShapeCluster)clusters.get(i)).draw(pa, path);
			}
		//}
	}

	public void keyAdded(Path p) {
		clusters.add(new ShapeCluster(this, p.getSize() - 1, clusterSize, width, shapeSize));
		if(clusters.size() > 1) getCluster(clusters.size()-2).clusterAdded();
		
	}
	
	public void keysAdded(Path p, int amount){
		
	}
	public ShapeCluster getCluster(int i){
		return (ShapeCluster)clusters.get(i);
	}

	public void keyRemoved(Path p, int i) {

			clusters.remove(i);
			for(int ci = 0; ci < clusters.size(); ci++){
				ShapeCluster c = (ShapeCluster)clusters.get(ci);
				if(c.pathIndex > i) c.pathIndex--;
			}
			getCluster(i).clusterRemoved();
	}
}
